package cn.antcore.common.access;

import org.aopalliance.intercept.MethodInvocation;
import org.springframework.expression.EvaluationContext;
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
import org.springframework.security.access.expression.method.MethodSecurityExpressionOperations;
import org.springframework.security.core.Authentication;

import java.util.function.Supplier;

/**
 * OAuth2权限验证
 * <br>
 * Created by Hong 2024/5/29
**/
public class OAuth2MethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler {

    private final PermissionEvaluator permissionEvaluator;

    public OAuth2MethodSecurityExpressionHandler(PermissionEvaluator permissionEvaluator) {
        this.permissionEvaluator = permissionEvaluator;
    }

    @Override
    public EvaluationContext createEvaluationContext(Supplier<Authentication> authentication, MethodInvocation mi) {
        MethodSecurityExpressionOperations root = createSecurityExpressionRoot(authentication, mi);
        OAuth2MethodSecurityEvaluationContext ctx = new OAuth2MethodSecurityEvaluationContext(root, mi,
                getParameterNameDiscoverer());
        ctx.setBeanResolver(getBeanResolver());
        return ctx;
    }

    @Override
    protected MethodSecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, MethodInvocation invocation) {
        OAuth2SecurityExpressionRoot root = new OAuth2SecurityExpressionRoot(authentication);
        root.setThis(invocation.getThis());
        root.setTrustResolver(getTrustResolver());
        root.setPermissionEvaluator(permissionEvaluator);
        root.setRoleHierarchy(getRoleHierarchy());
        return root;
    }

    private MethodSecurityExpressionOperations createSecurityExpressionRoot(Supplier<Authentication> authentication, MethodInvocation invocation) {
        OAuth2SecurityExpressionRoot root = new OAuth2SecurityExpressionRoot(authentication);
        root.setThis(invocation.getThis());
        root.setPermissionEvaluator(getPermissionEvaluator());
        root.setTrustResolver(getTrustResolver());
        root.setRoleHierarchy(getRoleHierarchy());
        root.setDefaultRolePrefix(getDefaultRolePrefix());
        return root;
    }
}
